package de.dopichaj.labrador.tools;


import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import de.dopichaj.labrador.index.Index;
import de.dopichaj.labrador.index.IndexVersionException;
import de.dopichaj.labrador.index.Tag;
import de.dopichaj.labrador.index.TagFactory;
import de.dopichaj.labrador.index.meta.BaselineDocumentMetaDataHuffmanOutput;
import de.dopichaj.labrador.index.meta.BaselineDocumentMetaDataInput;
import de.dopichaj.labrador.index.meta.BaselineDocumentMetaDataOutput;
import de.dopichaj.labrador.index.own.OwnFileSystemIndex;
import de.dopichaj.labrador.util.io.BitInputStream;
import de.dopichaj.labrador.util.io.BitOutputStream;
import de.dopichaj.labrador.util.io.ByteReader;
import de.dopichaj.labrador.util.io.ByteWriter;
import de.dopichaj.labrador.util.io.huffman.HuffmanDataWriter;
import de.dopichaj.labrador.util.io.huffman.HuffmanTree;


public final class DigestCompressor {

    public static void main(String[] args) throws IOException, IndexVersionException {

        if (args.length < 3) {
            System.err.println("Usage: DigestCompressor de.dopichaj.labrador.index frequency-tags prefix");
            System.exit(0);
        }
        final String prefix = args[2];
        
        final Index index = new OwnFileSystemIndex(new File(args[0]));
        final TagFactory inputTagFactory = index.getTagFactory();
        
        // build the Huffman tree
        final BufferedReader reader = new BufferedReader(new FileReader(args[1]));
        String line;
        final Map<Integer, Integer> map = new HashMap<Integer, Integer>();
        while ((line = reader.readLine()) != null) {
            final String[] parts = line.split("\t");
            map.put(inputTagFactory.getTag(parts[1]).getId(), Integer.valueOf(parts[0]));
        }
        final HuffmanTree<Integer> tree = new HuffmanTree<Integer>(map);
        System.out.print(tree);
        
        // write the huffman tree
        final ByteWriter huffmanByteWriter = new ByteWriter(new DataOutputStream(
            new FileOutputStream(prefix + "huffman")), 4096);
        final BitOutputStream bitOutputStream = new BitOutputStream(huffmanByteWriter);
        tree.writeTree(bitOutputStream, new HuffmanDataWriter<Integer>() {
            public void write(BitOutputStream output, Integer symbol) throws IOException {
                output.writeVariableLengthInt(symbol);
            }
        });
        bitOutputStream.close();
        
        // convert
        final ByteReader digestByteReader = index.getDigestByteReader();
        final ByteWriter digestByteWriter = new ByteWriter(new DataOutputStream(
            new FileOutputStream(prefix + "newdigest")), 4096);
        final BitOutputStream output = new BitOutputStream(digestByteWriter);
        
        try {
            while (true) {
                final BitInputStream bitInputStream = new BitInputStream(digestByteReader);
                
                output.writeString(bitInputStream.readString());
                output.writeVariableLengthInt(bitInputStream.readVariableLengthInt());
                final int elementCount = bitInputStream.readVariableLengthInt();
                output.writeVariableLengthInt(elementCount);
                
                final BaselineDocumentMetaDataInput input = index.getIOFactory().getInput(bitInputStream);
                final BaselineDocumentMetaDataOutput mdOutput = new BaselineDocumentMetaDataHuffmanOutput(output, tree);
    
                copyTagID(inputTagFactory, inputTagFactory, input, mdOutput);
                mdOutput.writeLengthDelta(input.readLengthDelta());
                
                for (int i = 1; i < elementCount; i++) {
                    mdOutput.writeIDDelta(input.readIDDelta());
                    copyTagID(inputTagFactory, inputTagFactory, input, mdOutput);
                    mdOutput.writePositionDelta(input.readPositionDelta());
                    mdOutput.writeLengthDelta(input.readLengthDelta());
                }
                bitInputStream.skipToNext();
                output.flush();
            }
        } catch (EOFException e) {
            output.close();
        }
    }

    private static void copyTagID(final TagFactory outputTagFactory, final TagFactory inputTagFactory, final BaselineDocumentMetaDataInput input, final BaselineDocumentMetaDataOutput mdOutput) throws IOException {
        final Tag rootTag = inputTagFactory.getTag(input.readTagID());
        mdOutput.writeTagID(outputTagFactory.getTag(rootTag.getName()).getId());
    }
}
/*
Copyright (c) 2007 Philipp Dopichaj

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/